/**
 * TODO: this class name may should be Scene or something.
 */
function PageMessage( game, strings, options ) {
  this.game = game ;
  this.count = 0 ;
  this.minX = 100 ;
  this.maxX = 380 ;
  this.minY = 100 ;
  this.maxY = 380 ;
  this.width = this.maxX - this.minX ;
  this.height = this.maxY - this.minY ;
  this.x = this.minX ;
  this.y = this.minY ;

  this.state = 0 ;
  this.flag = 0 ;

  this.strings = strings ;
  this.stopPoints = [ ] ;
  this.headIndex = 0 ;
  this.tailIndex = 0 ;

  this.options = options ;
  this.optionPosition = null ;

  this.stopStrings = [ '.', '。' ] ;
  this.fillStyle = 'black' ;
  this.font = '20px monospace' ;

  this._initStopPoints( ) ;

}

PageMessage._STATE_RUNNING = 0x0 ;
PageMessage._STATE_STOP    = 0x1 ;

PageMessage._FLAG_ALL_DISPLAYED     = 0x1 ;
PageMessage._FLAG_OPTIONS_DISPLAYED = 0x2 ;

PageMessage.prototype._initStopPoints = function( ) {
  for( var i = 0; i < this.strings.length; i++ ) {
    if( this.stopStrings.indexOf( this.strings[ i ] ) >= 0 )
      this.stopPoints.push( i + 1 ) ;
  }
} ;


PageMessage.prototype.runStep = function( ) {
  if( this.state == PageMessage._STATE_RUNNING ) {
    if( this.headIndex < this.strings.length ) {
      this.headIndex++ ;
    } else {
      this.state = PageMessage._STATE_STOP ;
      this.setFlag( PageMessage._FLAG_ALL_DISPLAYED ) ;
    }
    if( this.stopPoints.indexOf( this.headIndex ) >= 0 ) {
      this.state = PageMessage._STATE_STOP ;
    }
  }
  this.count++ ;
} ;


PageMessage.prototype.display = function( surface ) {
  this._displayMessage( surface ) ;
  this._displayOptions( surface ) ;
} ;


PageMessage.prototype._displayMessage = function( surface ) {
  if( this.tailIndex >= this.headIndex )
    return ;

  while( this.tailIndex < this.headIndex ) {
    var str = this.strings[ this.tailIndex ] ;
    this._putString( surface, str ) ;
    this.tailIndex++ ;
  }
} ;


PageMessage.prototype._displayOptions = function( surface ) {
  if( ! this.isFlagSet( PageMessage._FLAG_ALL_DISPLAYED ) ||
        this.isFlagSet( PageMessage._FLAG_OPTIONS_DISPLAYED ) )
    return ;

  this.optionPositions = [ ] ;

  this._putString( surface, '\n' ) ;
  for( var i = 0; i < this.options.length; i++ ) {
    var option = this.options[ i ] ;
    var range = { 'min': 0, 'max': 0 } ;
    range.min = this.y ;
    this._putStrings( surface, ( i + 1 ) + '. ' ) ;
    for( var j = 0; j < option.label.length; j++ ) {
      this._putString( surface, option.label[ j ] ) ;
    }
    range.max = this.y + 20 ;
    this.optionPositions.push( range ) ;
    this._putString( surface, '\n' ) ;
  }

  this.setFlag( PageMessage._FLAG_OPTIONS_DISPLAYED ) ;

} ;


PageMessage.prototype._putString = function( surface, str ) {
  if( str == '\n' ) {
    this._putNewLine( ) ;
  } else {
    surface.textBaseline = 'top' ;
    surface.textAlign = 'left' ;
    surface.fillStyle = this.fillStyle ;
    surface.font = this.font ;
    surface.fillText( str, this.x, this.y ) ;
    this._adjacentPosition( str ) ;
  }
} ;


PageMessage.prototype._putStrings = function( surface, str ) {
  for( var i = 0; i < str.length; i++ )
    this._putString( surface, str[ i ] ) ;
} ;


PageMessage.prototype._adjacentPosition = function( str ) {
  if( this._isStringFull( str ) )
    this.x += 20 ;
  else
    this.x += 10 ;

  if( this.x >= this.maxX ) {
    this.x = this.minX ;
    this.y += 20 ;
  }
} ;


PageMessage.prototype._putNewLine = function( ) {
  this.x = this.minX ;
  this.y += 20 ;
} ;


PageMessage.prototype.handleOnClick = function( e, x, y ) {
  if( this.state == PageMessage._STATE_STOP )
    this.state = PageMessage._STATE_RUNNING ;
  if( this.isFlagSet( PageMessage._FLAG_OPTIONS_DISPLAYED ) ) {
    for( var i = 0; i < this.optionPositions.length; i++ ) {
      if( y >= this.optionPositions[ i ].min &&
          y <  this.optionPositions[ i ].max ) {
        this.game.notifyOptionSelect( this.options[ i ].id ) ;
      }
    }
  }
} ;


PageMessage.prototype._isStringFull = function( str ) {
  var c = str.charCodeAt( 0 ) ;
  if( c < 256 || ( c >= 0xff61 && c <= 0xff9f ) )
    return false ;
  return true ;
} ;


PageMessage.prototype.getWidth = function( ) {
  return this.width ;
} ;


PageMessage.prototype.getHeight = function( ) {
  return this.height ;
} ;


PageMessage.prototype.isFlagSet = function( type ) {
  return ( this.flags & type ) ? true : false ;
} ;


PageMessage.prototype.setFlag = function( type ) {
  this.flags |= type ;
} ;


PageMessage.prototype.clearFlag = function( type ) {
  this.flags &= ~type ;
} ;
